package com.benyanyi.okhttp.call;

import android.content.Context;

import com.benyanyi.okhttp.config.CallType;
import com.benyanyi.okhttp.util.OkHttpLog;
import com.benyanyi.okhttp.util.CacheUtils;
import com.benyanyi.okhttp.util.FormatUtil;
import com.benyanyi.okhttp.util.Internet;
import com.benyanyi.okhttp.util.InternetBean;
import com.benyanyi.okhttp.listener.OnOkHttpListener;
import com.google.gson.Gson;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonParser;

import org.json.XML;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import io.reactivex.Observable;
import io.reactivex.ObservableEmitter;
import io.reactivex.ObservableOnSubscribe;
import io.reactivex.Observer;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.Disposable;
import io.reactivex.schedulers.Schedulers;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.Response;
import okhttp3.ResponseBody;

/**
 * @author YanYi
 * @date 2019-08-12 11:43
 * @email ben@yanyi.red
 * @overview
 */
class ListCall<T> {

    private Class<T> tClass;
    private CallType callType;
    private Call call;
    private boolean isCache;//是否需要缓存
    private String mCacheName;//缓存名称
    private Context context;
    private OnOkHttpListener<List<T>> onOkHttpListener;

    ListCall(CallBuilder builder, Class<T> tClass) {
        this.callType = builder.getCallType();
        this.call = builder.getCall();
        this.isCache = builder.isCache();
        this.mCacheName = builder.getCacheName();
        this.context = builder.getContext();
        this.tClass = tClass;
    }

    void send(OnOkHttpListener<List<T>> okHttpListener) {
        this.onOkHttpListener = okHttpListener;
        InternetBean internetBean = Internet.ifInternet(context);
        if (internetBean.getStatus()) {
            sendCall().subscribeOn(Schedulers.io())
                    .observeOn(AndroidSchedulers.mainThread())
                    .serialize()
                    .subscribe(new Observer<List<T>>() {
                        @Override
                        public void onSubscribe(Disposable d) {

                        }

                        @Override
                        public void onNext(List<T> t) {
                            onOkHttpListener.onSuccess(t);
                        }

                        @Override
                        public void onError(Throwable e) {
                            onOkHttpListener.onFailure(e);
                        }

                        @Override
                        public void onComplete() {
                            onOkHttpListener.onCompleted();
                        }
                    });
        } else {
            if (isCache) {
                String str = CacheUtils.getInstance(context).getCacheToLocalJson(mCacheName);
                onOkHttpListener.onSuccess(dataToT(str));
            }
            onOkHttpListener.onFailure(new Exception(internetBean.getMsg()));
            onOkHttpListener.onCompleted();
        }
    }

    private Observable<List<T>> sendCall() {
        return Observable.create(new ObservableOnSubscribe<List<T>>() {
            @Override
            public void subscribe(ObservableEmitter<List<T>> emitter) throws Exception {
                send(emitter);
            }
        });
    }

    private void send(ObservableEmitter<List<T>> emitter) {
        if (callType == CallType.ASYNC) {
            async(emitter);
        } else {
            sync(emitter);
        }
    }

    private void async(final ObservableEmitter<List<T>> emitter) {
        call.enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                OkHttpLog.e(e.getMessage());
                emitter.onError(e);
                emitter.onComplete();
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                success(response, emitter);
            }
        });
    }

    private void sync(ObservableEmitter<List<T>> emitter) {
        try {
            Response response = call.execute();
            success(response, emitter);
        } catch (Exception e) {
            OkHttpLog.e(e.getMessage());
            emitter.onError(e);
            emitter.onComplete();
        }
    }

    private void success(Response response, ObservableEmitter<List<T>> emitter) throws IOException {
        ResponseBody body = response.body();
        if (body != null && response.code() == 200) {
            if (response.isSuccessful()) {
                if (response.networkResponse() != null) {//网络请求有数据
                    String str = body.string();
                    List<T> t = dataToT(dataProcessing(str));
                    emitter.onNext(t);
                    emitter.onComplete();
                } else {
                    dataReturn(body.string(), emitter);
                }
            } else {
                dataReturn(body.string(), emitter);
            }
        } else {
            dataReturn(null, emitter);
        }
    }

    /**
     * 数据处理
     */
    private String dataProcessing(String message) {
        String str = message;
        OkHttpLog.d(str);
        String html = "<!DOCTYPE HTML>";
        if (FormatUtil.isNotEmpty(str) && !str.toUpperCase().contains(html) && isCache) {
            if (FormatUtil.isNotEmpty(mCacheName)) {
                CacheUtils.getInstance(context).setCacheToLocalJson(mCacheName, str);
            }
        } else {
            if (isCache) {
                str = CacheUtils.getInstance(context).getCacheToLocalJson(mCacheName);
            }
        }
        return str;
    }

    /**
     * 数据返回
     *
     * @param message
     * @param emitter
     */
    private void dataReturn(String message, ObservableEmitter<List<T>> emitter) {
        if (isCache) {
            List<T> list = dataToT(CacheUtils.getInstance(context).getCacheToLocalJson(mCacheName));
            emitter.onNext(list);
            emitter.onComplete();
        } else {
            List<T> list = dataToT(dataProcessing(message));
            emitter.onNext(list);
            emitter.onComplete();
        }
    }

    private List<T> dataToT(String data) {
        String str = data;
        List<T> list = new ArrayList<>();
        if (FormatUtil.isEmpty(str)) {
            return list;
        }
        boolean boo = ("<".equals(str.substring(0, 1)) || "[".equals(str.substring(0, 1)))
                && ("\"".equals(str.substring(1, 2)) || "[".equals(str.substring(1, 2)));
        if (boo) {
            try {
                str = XML.toJSONObject(str).toString();
            } catch (Exception e) {
                OkHttpLog.e(e.getMessage());
            }
        }
        try {
//            JsonParser jsonParser = new JsonParser();
//            JsonElement parse = jsonParser.parse(str);
            JsonElement parse = JsonParser.parseString(str);
            Gson gson = new Gson();
            if (parse.isJsonArray()) {
                JsonArray array = parse.getAsJsonArray();
                for (int i = 0; i < array.size(); i++) {
                    T t = gson.fromJson(array.get(i).getAsJsonObject(), tClass);
                    list.add(t);
                }
            } else {
                T t = gson.fromJson(str, tClass);
                list.add(t);
            }
        } catch (Exception e) {
            OkHttpLog.e(e.getMessage());
        }
        return list;
    }
}
